package com.ruoyi.coal.common.utils;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.ruoyi.coal.modules.coalpile.domain.vo.PdfVo;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.springframework.core.io.ClassPathResource;

public class WordUtils {
    public static void changeText(XWPFDocument document, Map<String, Object> textMap) {
        Iterator<XWPFParagraph> iterator = document.getParagraphsIterator();
        XWPFParagraph paragraph = null;
        while (iterator.hasNext()) {
            paragraph = iterator.next();
            if (checkText(paragraph.getText()))
                replaceValue(paragraph, textMap);
        }
    }

    public static boolean checkText(String text) {
        boolean check = false;
        if (text.contains("$"))
            check = true;
        return check;
    }

    public static void changePic(XWPFDocument document, Map<String, Object> picData) throws Exception {
        Iterator<XWPFParagraph> iterator = document.getParagraphsIterator();
        while (iterator.hasNext()) {
            XWPFParagraph paragraph = iterator.next();
            String text = paragraph.getText();
            if (checkText(text))
                replacePicValue(paragraph, picData);
        }
    }

    public static void changeTableText(XWPFDocument document, Map<String, Object> data) {
        Iterator<XWPFTable> tableList = document.getTablesIterator();
        while (tableList.hasNext()) {
            XWPFTable table = tableList.next();
            if (checkText(table.getText())) {
                List<XWPFTableRow> rows = table.getRows();
                for (XWPFTableRow row : rows) {
                    List<XWPFTableCell> cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        if (checkText(cell.getText())) {
                            List<XWPFParagraph> paragraphs = cell.getParagraphs();
                            for (XWPFParagraph paragraph : paragraphs)
                                replaceValue(paragraph, data);
                        }
                    }
                }
            }
        }
    }

    public static void changeTablePic(XWPFDocument document, Map<String, Object> picData) throws Exception {
        Iterator<XWPFTable> tableList = document.getTablesIterator();
        while (tableList.hasNext()) {
            XWPFTable table = tableList.next();
            if (checkText(table.getText())) {
                List<XWPFTableRow> rows = table.getRows();
                for (XWPFTableRow row : rows) {
                    List<XWPFTableCell> cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        if (checkText(cell.getText())) {
                            List<XWPFParagraph> paragraphs = cell.getParagraphs();
                            for (XWPFParagraph paragraph : paragraphs)
                                replacePicValue(paragraph, picData);
                        }
                    }
                }
            }
        }
    }

    public static void replaceValue(XWPFParagraph paragraph, Map<String, Object> textMap) {
        List<XWPFRun> runs = paragraph.getRuns();
        for (int i = 0; i < runs.size(); i++) {
            XWPFRun run = runs.get(i);
            String runsText = run.getText(0);
            if (runsText.contains("${") || (runsText.contains("$") && ((XWPFRun)runs.get(i + 1)).getText(0).substring(0, 1).equals("{"))) {
                while (!runsText.contains("}")) {
                    XWPFRun nextRun = runs.get(i + 1);
                    runsText = runsText + nextRun.getText(0);
                    paragraph.removeRun(i + 1);
                }
                Object value = changeValue(runsText, textMap);
                if (textMap.containsKey(runsText)) {
                    run.setText(value.toString(), 0);
                } else {
                    run.setText(runsText, 0);
                }
            }
        }
    }

    public static void replacePicValue(XWPFParagraph paragraph, Map<String, Object> picData) throws Exception {
        List<XWPFRun> runs = paragraph.getRuns();
        for (XWPFRun run : runs) {
            Object value = changeValue(run.toString(), picData);
            if (picData.containsKey(run.toString())) {
                run.setText("", 0);
                FileInputStream is = new FileInputStream((String)value);
                int width = Units.toEMU(450.0D), height = Units.toEMU(183.0D);
                run.addPicture(is, 6, (String)value, width, height);
            }
        }
    }

    public static Object changeValue(String value, Map<String, Object> textMap) {
        Object valu = "";
        for (Map.Entry<String, Object> textSet : textMap.entrySet()) {
            String key = textSet.getKey();
            if (value.contains(key))
                valu = textSet.getValue();
        }
        return valu;
    }

    public static ByteArrayOutputStream generatePdf(PdfVo data) throws IOException, DocumentException {
        ClassPathResource classPathResource = new ClassPathResource("template/coalPDF.pdf");
        InputStream PdfInputStream = classPathResource.getInputStream();
        PdfReader reader = new PdfReader(PdfInputStream);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        PdfStamper ps = new PdfStamper(reader, bos);
        BaseFont baseFont = BaseFont.createFont("template/simsun.ttf", "Identity-H", false, false);
        ArrayList<BaseFont> fontArrayList = new ArrayList<>();
        fontArrayList.add(baseFont);
        AcroFields s = ps.getAcroFields();
        s.setSubstitutionFonts(fontArrayList);
        ps.getAcroFields().getFields().forEach((field, item) -> {
            try {
                if (field.startsWith("CreateTime"))
                    ps.getAcroFields().setField(field, DateUtils.format(data.getCoalPileInfoEntity().getCreateTime(), "yyyy-MM-dd HH:mm"));
                if (!field.startsWith("Url") && !field.startsWith("CreateTime")) {
                    String getterName = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
                    Method method = data.getCoalPileInfoEntity().getClass().getMethod(getterName, new Class[0]);
                    Object value = method.invoke(data.getCoalPileInfoEntity(), new Object[0]);
                    ps.getAcroFields().setField(field, String.valueOf(value));
                } else {
                    int pageNo = ((AcroFields.FieldPosition)s.getFieldPositions("UrlImage2").get(0)).page;
                    Rectangle signRect = ((AcroFields.FieldPosition)s.getFieldPositions("UrlImage2").get(0)).position;
                    float x = signRect.getLeft();
                    float y = signRect.getBottom();
                    Image image = Image.getInstance(new URL(data.getCoalPileInfoEntity().getUrlImage2()));
                    PdfContentByte under = ps.getOverContent(pageNo);
                    image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                    image.setAbsolutePosition(x, y);
                    under.addImage(image);
                }
            } catch (NoSuchMethodException|IllegalAccessException|java.lang.reflect.InvocationTargetException e) {
                throw new RuntimeException("获取字段值失败");
            } catch (DocumentException|IOException e) {
                throw new RuntimeException("填充数据失败");
            }
        });
        ps.setFormFlattening(true);
        ps.close();
        return bos;
    }
}

